/**
 * @file Voice_module.cpp
 * @brief 语音模块功能实现文件，负责语音命令的接收、解析和处理
 * @author 15548
 * @date 2025/2/27
 */
#include <Arduino.h>
#include "Voice_module.h"
#include <BLE2902.h>
#include "hbot_motion.h"
#include <vector>
#include "A_Star.h"
#include <SoftwareSerial.h> // 引入软串口库
#include "hall_id.h"

// 函数声明
// void initVoiceSerial();
void processVoiceCommand(uint8_t command);
// 初始化软串口
SoftwareSerial Serial3(46, 3); // RX: 46, TX: 3

// 声明任务句柄和信号量
TaskHandle_t voiceSerialTaskHandle = NULL;
SemaphoreHandle_t voiceMutex = NULL;

/**
 * @brief 向语音模块发送数据帧，用于输出音频
 * @param command 要发送的命令字节
 */
void sendFrameToVoiceModule(uint8_t command)
{
    // 检查语音模块状态和串口是否准备好
    if (Serial3)
    {
        // 固定的帧头和帧尾
        const uint8_t frameHeader[] = {0xAA, 0x55};
        const uint8_t frameFooter[] = {0x55, 0xAA};

        // 发送帧头
        Serial3.write(frameHeader, 2);

        // 发送命令
        Serial3.write(command);

        // 发送帧尾
        Serial3.write(frameFooter, 2);

        if (print_key)
        {
            Serial.printf("发送命令 0x%02X 到语音模块\n", command);
        }
    }
    else
    {
        if (print_key)
        {
            Serial.println("语音模块未启用或串口未准备好，无法发送命令");
        }
    }
}

/**
 * @brief 串口接收解析16进制数据任务
 * @param pvParameters 任务参数（未使用）
 * @note 此任务运行在Core 0 (APP_CPU)上，负责从软串口接收语音模块数据
 */
void serialTask(void *pvParameters)
{

    Serial3.begin(115200); // 使用软串口初始化
    while (!Serial3)
    {
        ; // 等待串口 3 准备好，串口三为esp32的串口
        if (print_key)
        {
            Serial.println("串口 3 未准备好，等待...");
        }
        delay(1000);
    }
    if (print_key)
    {
        Serial.println("ESP32 串口接收解析 16 进制任务已启动");
    }

    while (true)
    {
        while (Serial3.available() > 0)
        {
            byte incomingByte = Serial3.read();
            // 调试每个收到的字节
            if (print_key)
            {
                Serial.printf("收到字节: 0x%02X\n", incomingByte);
            }
            processVoiceCommand(incomingByte);
        }
        vTaskDelay(50 / portTICK_PERIOD_MS);
    }
}

/**
 * @brief 处理接收到的语音模块命令
 * @param command 接收到的命令字节
 * @details 根据不同的命令字节执行相应的操作，如难度等级调整、音量控制等
 */
void processVoiceCommand(uint8_t command)
{
    if (print_key)
    {
        Serial.printf("处理语音命令: 0x%02X\n", command);
    }

    if (command == 0x01)
    {
        if (print_key)
        {
            Serial.println("收到命令: check board");
        }
    }
    else if (command == 0x02)
    {
        if (print_key)
        {
            Serial.println("收到命令: Start game");
        }
        //定义是创建变量，分配空间，声明是告诉编译器变量在哪声明过，可以引用
        Command cmd;
        cmd.cmd_name = "Start_game";
        cmdName = String("Start_game");
        // 通过蓝牙发送命令
        if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        {
            if (print_key)
            {
                Serial.println("命令队列已满，无法添加特殊启动命令");
            }
        }
    }
    else if (command == 0x03)
    {
        if (print_key)
        {
            Serial.println("收到语音命令: level up");
        }
        // if (level_difficulty_g < 10)
        // {
        //     level_difficulty_g += 1;
        // }
        // else
        // {
        //     Serial.println("到达最高难度等级！");
        // }
        // Command cmd;
        // cmd.cmd_name = "level";
        // cmd.level = level_difficulty_g;
        // Serial.print("level:");
        // Serial.println(level_difficulty_g);
        // // 通过蓝牙发送命令
        // if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        // {
        //     Serial.println("命令队列已满，无法添加特殊启动命令");
        // }
        Command cmd;
        cmd.cmd_name = "level_up";
        cmdName = String("level_up");
        // 通过蓝牙发送命令
        if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        {
            if (print_key)
            {
                Serial.println("命令队列已满，无法添加特殊启动命令");
            }
        }
    }
    else if (command == 0x04)
    {
        if (print_key)
        {
            Serial.println("收到命令: level down");
        }
        // if (level_difficulty_g > 1)
        // {
        //     level_difficulty_g -= 1;
        // }
        // else
        // {
        //     Serial.println("到达最低难度等级！");
        // }
        // Command cmd;
        // cmd.cmd_name = "level";
        // cmd.level = level_difficulty_g;
        // Serial.print("level:");
        // Serial.println(level_difficulty_g);
        // // 通过蓝牙发送命令
        // if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        // {
        //     Serial.println("命令队列已满，无法添加特殊启动命令");
        // }
        Command cmd;
        cmd.cmd_name = "level_down";
        cmdName = String("level_down");
        // 通过蓝牙发送命令
        if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        {
            if (print_key)
            {
                Serial.println("命令队列已满，无法添加特殊启动命令");
            }
        }
    }
    else if (command == 0x05)
    {
        if (print_key)
        {
            Serial.println("收到命令: volume up");
        }
    }
    else if (command == 0x06)
    {
        if (print_key)
        {
            Serial.println("收到命令: volume down");
        }
    }
    else if (command == 0x07)
    {
        if (print_key)
        {
            Serial.println("收到命令: Take back");
        }

        Command cmd;
        cmd.cmd_name = "take_back";
        cmdName = String("take_back");
        // 通过蓝牙发送命令
        if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        {
            if (print_key)
            {
                Serial.println("命令队列已满，无法添加特殊启动命令");
            }
        }
        // take_back();
    }
    else if (command == 0x08)
    {
        if (print_key)
        {
            Serial.println("收到命令: save game");
        }
    }
    else if (command == 0x09)
    {
        if (print_key)
        {
            Serial.println("收到命令: special");
        }
        Command cmd;
        cmd.cmd_name = "special_start";
        cmdName = String("special_start");
        // 通过蓝牙发送命令
        if (xQueueSend(commandQueue, &cmd, portMAX_DELAY) != pdPASS)
        {
            if (print_key)
            {
                Serial.println("命令队列已满，无法添加特殊启动命令");
            }
        }
    }
    else
    {
        if (print_key)
        {
            Serial.printf("未知命令: 0x%02X\n", command);
        }
    }
}

/**
 * @brief 根据speaker_g状态更新语音模块信号量
 * @param enabled true表示启用语音模块，false表示禁用
 */
void updateVoiceStatus(bool enabled)
{
    static bool lastState = false;

    // 状态有变化时才执行
    if (enabled != lastState)
    {
        if (enabled)
        {
            // 释放信号量，允许执行任务
            xSemaphoreGive(voiceMutex);
            if (print_key)
            {
                Serial.println("语音模块已启用");
            }
        }
        else
        {
            // 获取信号量但不释放，阻止任务执行
            xSemaphoreTake(voiceMutex, portMAX_DELAY);
            if (print_key)
            {
                Serial.println("语音模块已禁用");
            }
        }
        lastState = enabled;
    }
}

/**
 * @brief 初始化语音模块
 * @details 创建互斥信号量并根据初始状态设置，创建语音串口任务
 */
void voice_init()
{
    // 创建互斥信号量
    voiceMutex = xSemaphoreCreateMutex();
    if (voiceMutex == NULL)
    {
        if (print_key)
        {
            Serial.println("无法创建语音模块互斥量");
        }
        return;
    }

    // 初始状态根据speaker_g设置，默认是ture
    if (!speaker_g)
    {
        xSemaphoreTake(voiceMutex, portMAX_DELAY); // 如果初始状态关闭，获取信号量阻止任务运行
    }

    // 创建串口接收任务并指定运行在Core 0 (APP_CPU)上
    xTaskCreatePinnedToCore(
        serialTask,             // 任务函数
        "VoiceSerialTask",      // 任务名称
        4096,                   // 任务栈大小
        NULL,                   // 任务参数
        1,                      // 优先级
        &voiceSerialTaskHandle, // 保存任务句柄
        0                       // 在Core 0上运行（ESP32S3的APP_CPU）
    );
}
